﻿namespace GGF
{
    using API;

    namespace Utility
    {
        using System;
        using System.Collections.Generic;
        using System.Text;
        using System.IO;
        using System.Xml;
        using System.Diagnostics;

        /// <summary>
        /// Concrete class that implements <see cref="GGF.Utility.IStreamHelper"/>
        /// interface. Meant to show how helper object interacts
        /// with a <see cref="GGF.REST.gResponse"/>. Works
        /// on XML data returned from API.
        /// </summary>
        public class gXmlStreamHelper : IStreamHelper
        {
            XmlTextReader readerXml;
            Dictionary<int, gList> userListCollection;

            /// <summary>
            /// Initial method used by helper for receiving stream from <see cref="GGF.REST.gResponse"/>.
            /// </summary>
            /// <param name="reader">A <see cref="System.IO.StreamReader"/> that has XML
            /// content ready to be parsed. Calls <c>process</c> method at the end which
            /// does most of the "heavy lifting."</param>
            /// <returns>Nothing.</returns>
            public void formatSpecificHelper(StreamReader reader)
            {
                userListCollection = new Dictionary<int, gList>();

                readerXml = new XmlTextReader(reader);
                readerXml.MoveToContent();
                readerXml.ReadToDescendant("list");

                process(readerXml, 0);
            }

            ///<summary>
            ///Gets the item's helper type (the type of data that helper parses).
            ///</summary>
            /// <value>
            /// The item's helper type represented by a standard .NET string.
            /// </value>
            public string helperType { get { return "XML"; } }

            /// <summary>
            /// Method that takes a <see cref="System.Object"/> that is later
            /// casted to either an <see cref="System.Xml.XmlReader"/> or
            /// <see cref="System.Xml.XmlTextReader"/>. After this method
            /// terminates, the object should have a collection of all the
            /// user's lists and their respective items (with all the parameters
            /// that GGF supports for the item or list).
            /// </summary>
            /// <param name="readerObj">An <see cref="System.Object"/> representing
            /// here a reader to "pull" data from. Later casted; see summary.</param>
            /// <param name="previousListId">An int representing the ID of the list that
            /// the item belongs to (via a recursive call) or (0) if it is still processing
            /// a list.
            /// </param>
            /// <returns>Nothing.</returns>
            public void process(object readerObj, int previousListId)
            {
                int itemCount;
                int itemOrListId;

                gList workList;
                gItem workItem;

                XmlReader workReader;

                int listCount = 0;

                string testString;

                if (previousListId == 0)
                    workReader = (XmlTextReader)readerObj;
                else
                    workReader = (XmlReader)readerObj;
                
                
                //still working with full tree (at <lists>) at loop start
                do
                {
                    if (previousListId == 0)
                    {
                        workReader = (XmlTextReader)readerObj;

                        workReader.ReadToDescendant("id");
                        itemOrListId = workReader.ReadElementContentAsInt();

                        workList = new gList(itemOrListId);

                        workReader.ReadToFollowing("name");
                        workList.name = workReader.ReadElementContentAsString();

                        workReader.ReadToFollowing("description");
                        workList.description = workReader.ReadElementContentAsString();

                        userListCollection.Add(itemOrListId, new gList(itemOrListId));
                        Debug.WriteLine("New list instantiated. id = " + itemOrListId, "List creation");

                        workReader.ReadToFollowing("items");

                        process(workReader.ReadSubtree(), itemOrListId); //passing <items> (with descendants) of list here

                        listCount++;
                    }
                    else
                    {
                        itemCount = 0;

                        if (workReader.ReadToDescendant("item"))
                        {
                            do
                            {
                                workReader.ReadToDescendant("id");
                                itemOrListId = workReader.ReadElementContentAsInt();

                                workItem = new gItem(itemOrListId);

                                workReader.ReadToFollowing("list_id");
                                workItem.list_id = workReader.ReadElementContentAsInt();

                                workReader.ReadToFollowing("note");
                                workItem.note = workReader.ReadElementContentAsString();

                                workReader.ReadToFollowing("details");
                                workItem.details = workReader.ReadElementContentAsString();

                                workReader.ReadToFollowing("date_due");
                                testString = workReader.ReadElementContentAsString();
                                if (testString != "")                                
                                    workItem.date_due = DateTime.Parse(testString);

                                workReader.ReadToFollowing("priority");
                                testString = workReader.ReadElementContentAsString();
                                if (testString != "")
                                    workItem.priority = Int32.Parse(testString);

                                userListCollection[previousListId].addItem(workItem);

                                Debug.WriteLine("New item instantiated. id = " + itemOrListId, "Item creation");

                                itemCount++;

                            } while (workReader.ReadToFollowing("item"));

                            
                        }

                        Console.WriteLine("Total number of items for list {0} : {1}", previousListId, itemCount);
                    }

                    

                } while (workReader.ReadToFollowing("list"));

                if( previousListId == 0 )
                    Console.WriteLine("Total number of lists : {0}", listCount);

                workReader.Close();

            } //end process method

        } //end class gXmlStreamHelper

    } //end namespace Utility

} //end namespace GGF
